/*
 * Copyright (c) 2020-2022 Jinsp-tech. All rights reserved.
 */

package com.jinsp.networklibrary;

import android.text.TextUtils;

import com.jinsp.networklibrary.command.CommandManager;
import com.jinsp.networklibrary.command.TCPBaseDataBeanFactory;
import com.jinsp.networklibrary.command.TCPCommandFactory;
import com.jinsp.networklibrary.filter.JsonCipherFilter;
import com.jinsp.networklibrary.filter.JsonFilter;
import com.jinsp.networklibrary.util.AESUtils;

import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
import org.apache.mina.filter.keepalive.KeepAliveFilter;
import org.apache.mina.filter.keepalive.KeepAliveRequestTimeoutHandler;
import org.apache.mina.filter.logging.LoggingFilter;
import org.apache.mina.transport.socket.nio.NioSocketConnector;

import java.net.InetSocketAddress;
import java.nio.charset.Charset;

/**
 * Created by luoshuai on 1/13/22
 * <p>
 * 连接管理类
 */
public class TCPConnectManager {

    private final TCPConnectConfig tcpConnectConfig;
    private InetSocketAddress mInetSocketAddress;
    private NioSocketConnector mNioSocketConnector;
    private ConnectFuture connectFuture;

    public TCPConnectManager(TCPConnectConfig tcpConnectConfig) {
        this.tcpConnectConfig = tcpConnectConfig;
        //初始化命令分发器
        CommandManager.getInstance().init();
        initTCP();
    }

    private void initTCP() {
        int port = tcpConnectConfig.getServicePort();
        if (port < 0) {
            port = 8080;
        }
        mInetSocketAddress = new InetSocketAddress(tcpConnectConfig.getServiceIP(), port);
        mNioSocketConnector = new NioSocketConnector();
        //设置读取缓冲大小
        mNioSocketConnector.getSessionConfig().setReaderIdleTime(tcpConnectConfig.getReadIdleTime());
        mNioSocketConnector.getSessionConfig().setReadBufferSize(10240);
        mNioSocketConnector.setConnectTimeoutMillis(tcpConnectConfig.getConnectTimeOut() * 1000);
        mNioSocketConnector.setHandler(new TCPMessageHandler());
        //日期过滤器
        mNioSocketConnector.getFilterChain().addLast("data_log", new LoggingFilter());
        //编解码过滤器
        TextLineCodecFactory textLineCodecFactory = new TextLineCodecFactory(Charset.forName(tcpConnectConfig.getCodeFormat()));
        textLineCodecFactory.setDecoderMaxLineLength(tcpConnectConfig.getDecoderMaxLineLength());
        mNioSocketConnector.getFilterChain().addLast("text_coder", new ProtocolCodecFilter(textLineCodecFactory));
        if (!TextUtils.isEmpty(tcpConnectConfig.getCipher())) {
            AESUtils.init(tcpConnectConfig.getCipher(), tcpConnectConfig.getCodeFormat());
            //加解密过滤器
            mNioSocketConnector.getFilterChain().addLast("data_cipher", new JsonCipherFilter());
        }
        if (tcpConnectConfig.isJsonData()) {
            //转换json过滤器
            mNioSocketConnector.getFilterChain().addLast("data_send_json",
                    new JsonFilter(tcpConnectConfig.getClientStateData(), tcpConnectConfig.isSendDataForJsonString()));
        }
        //心跳
        if (tcpConnectConfig.isUseHeartBeat()) {
            TCPHearBeatFactory tcpHearBeatFactory = new TCPHearBeatFactory(tcpConnectConfig.getHeartBeatCommandNumber(),
                    tcpConnectConfig.getClientStateData());
            KeepAliveFilter heartBeat = new KeepAliveFilter(tcpHearBeatFactory, IdleStatus.BOTH_IDLE,
                    KeepAliveRequestTimeoutHandler.CLOSE);
            heartBeat.setForwardEvent(false);
            heartBeat.setRequestInterval(tcpConnectConfig.getHeartBeatInterval());
            heartBeat.setRequestTimeout(tcpConnectConfig.getHeartBeatTimeOut());
            mNioSocketConnector.getFilterChain().addLast("data_heartbeat", heartBeat);
        }
    }

    /**
     * 建立连接
     *
     * @return true -- 连接成功
     */
    public boolean connect() {
        connectFuture = mNioSocketConnector.connect(mInetSocketAddress);
        connectFuture.awaitUninterruptibly();
        if (!connectFuture.isConnected()) {
            connectFuture = null;
            return false;
        }
        IoSession session = connectFuture.getSession();
        //保存会话
        TCPSessionManager.getInstance().setNioSocketConnector(mNioSocketConnector);
        TCPSessionManager.getInstance().setIoSession(session);
        //重置读取空闲状态
        TCPSessionManager.getInstance().setTcpReadIdle(false);
        connectFuture = null;
        return true;
    }

    /**
     * 关闭并释放连接
     */
    public void disconnect() {
        if (connectFuture != null) {
            connectFuture.cancel();
            connectFuture = null;
        }
        TCPSessionManager.getInstance().release();
        TCPCommandFactory.release();
        TCPBaseDataBeanFactory.release();
    }
}
